// Copyright (c) Appeon. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.

using System;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;

namespace SnapObjects.Data
{
    /// <summary>
    ///     Provides a series of methods for manipulating the data in the embedded properties of TModel.
    /// </summary>
    /// <typeparam name="TModel">The type of a model class.</typeparam>
    public interface IEmbeddedLoadable<TModel>
    {
        /// <summary>
        ///     Get a reference to the master model object which is passed in as an argument when the 
        ///     ISqlModelMapper.TrackMaster method is called.
        /// </summary>
        TModel MasterModel { get; }

        /// <summary>
        ///     Loads data for the specified embedded property in TModel for all rows. If the ModelEmbedded attribute 
        ///     is applied in the property, the property will use the SQL query(defined in the detail model class 
        ///     specified by the ModelType property of the ModelEmbedded attribute) to retrieve data from database.
        ///     The cascade parameter can be used to decide whether to retrieve data for the embedded properties 
        ///     in the detail model or the granddetail model.
        /// </summary>
        /// <param name="property">
        ///     An embedded property of TModel class.
        ///     This property is specified by an expression.
        /// </param>
        /// <param name="cascade">
        ///     Only when the ModelEmbedded attribute is applied in the property, the cascade parameter can be used 
        ///     to decide whether to retrieve data for the embedded properties in the detail model or the granddetail
        ///     model. See master-detail-granddetail for more info. The default value is false.
        /// </param>
        /// <returns>
        ///     Returns the current <see cref="IEmbeddedLoadable{TModel}"/> object whose methods can be used to further obtain 
        ///     the data result set or perform data operations such as embedded queries.
        /// </returns>
        IEmbeddedLoadable<TModel> Include(Expression<Func<TModel, object>> property, bool cascade = false);

        /// <summary>
        ///     Asynchronously loads data for the specified embedded property in TModel for all rows. If the ModelEmbedded attribute 
        ///     is applied in the property, the property will use the SQL query(defined in the detail model class 
        ///     specified by the ModelType property of the ModelEmbedded attribute) to retrieve data from database.
        ///     The cascade parameter can be used to decide whether to retrieve data for the embedded properties 
        ///     in the detail model or the granddetail model.
        /// </summary>
        /// <param name="property">
        ///     An embedded property of TModel class.
        ///     This property is specified by an expression.
        /// </param>
        /// <param name="cascade">
        ///     Only when the ModelEmbedded attribute is applied in the property, the cascade parameter can be used 
        ///     to decide whether to retrieve data for the embedded properties in the detail model or the granddetail
        ///     model. See master-detail-granddetail for more info. The default value is false.
        /// </param>
        /// <param name="cancellationToken">
        ///     (Optional) A cancellation token that can be used by other objects or threads to receive notice of cancellation.
        /// </param>
        /// <returns>
        ///     Returns a task that represents the asynchronous operation.
        /// </returns>
        Task<IEmbeddedLoadable<TModel>> IncludeAsync(
            Expression<Func<TModel, object>> property, bool cascade = false, CancellationToken cancellationToken = default);

        /// <summary>
        ///     Loads data for the embedded properties in TModel for all rows. If the ModelEmbedded attribute is applied 
        ///     in the property, the property will use the SQL query(defined in the detail model class specified by the 
        ///     ModelType property of the ModelEmbedded attribute) to retrieve data from database.The cascade parameter 
        ///     can be used to decide whether to retrieve data for the embedded properties in the detail model or the 
        ///     granddetail model.
        /// </summary>
        /// <param name="cascade">
        ///     Only when the ModelEmbedded attribute is applied in the property, the cascade parameter can be used to 
        ///     decide whether to retrieve data for the embedded properties in the detail model or the granddetail model. 
        ///     See master-detail-granddetail for more info.The default value is false.
        /// </param>
        /// <returns>
        ///     Returns an <see cref="IEmbeddedLoadable{TModel}"/> object whose methods can be used to further obtain the data result
        ///     set or perform data operations such as embedded queries.
        /// </returns>
        IEmbeddedLoadable<TModel> IncludeAll(bool cascade = false);

        /// <summary>
        ///     Asynchronously loads data for the embedded properties in TModel for all rows. If the ModelEmbedded attribute is applied 
        ///     in the property, the property will use the SQL query(defined in the detail model class specified by the 
        ///     ModelType property of the ModelEmbedded attribute) to retrieve data from database.The cascade parameter 
        ///     can be used to decide whether to retrieve data for the embedded properties in the detail model or the 
        ///     granddetail model.
        /// </summary>
        /// <param name="cascade">
        ///     Only when the ModelEmbedded attribute is applied in the property, the cascade parameter can be used to 
        ///     decide whether to retrieve data for the embedded properties in the detail model or the granddetail model. 
        ///     See master-detail-granddetail for more info.The default value is false.
        /// </param>
        /// <param name="cancellationToken">
        ///     (Optional) A cancellation token that can be used by other objects or threads to receive notice of cancellation.
        /// </param>
        /// <returns>
        ///     Returns a task that represents the asynchronous operation.
        /// </returns>
        Task<IEmbeddedLoadable<TModel>> IncludeAllAsync(bool cascade = false, CancellationToken cancellationToken = default);
    }
}
